package cn.feizhu.aimarket.ai.workflow.node;

import cn.feizhu.aimarket.ai.workflow.model.constant.WorkflowControlConstant;
import cn.feizhu.aimarket.ai.workflow.model.enums.NodeStatus;
import cn.feizhu.aimarket.ai.workflow.service.WorkflowDataService;
import cn.feizhu.aimarket.model.enums.FileDirBizEnums;
import cn.feizhu.aimarket.tools.MinioUtils;
import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.action.NodeAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 可视化节点
 * 将聚合后的内容进行可视化处理，生成展示页面
 *
 * @author feizhu
 * @since 2025/10/16
 */
public class VisualizationNode implements NodeAction {

    private static final Logger logger = LoggerFactory.getLogger(VisualizationNode.class);

    private final MinioUtils minioUtils;
    private final WorkflowDataService workflowDataService;
    private final Map<String, NodeStatus> node2Status;
    
    public static final String NODE_NAME = "visualization";

    public VisualizationNode(MinioUtils minioUtils, WorkflowDataService workflowDataService, Map<String, NodeStatus> node2Status) {
        this.minioUtils = minioUtils;
        this.workflowDataService = workflowDataService;
        this.node2Status = node2Status;
    }

    @Override
    public Map<String, Object> apply(OverAllState state) {
        node2Status.put(NODE_NAME, NodeStatus.RUNNING);
        logger.info("=== 可视化节点开始执行 ===");

        try {
            // 获取聚合后的内容
            String aggregatedContent = (String) state.value(WorkflowControlConstant.AGGREGATED_CONTENT)
                    .orElse("未找到聚合内容");

            // TODO 暂时把用户输入当做标题
            String userInput = (String) state.value(WorkflowControlConstant.USER_INPUT)
                    .orElse("智能内容生成结果");
            logger.info("开始对聚合内容进行可视化处理");

            // 获取用户ID
            long userId = Long.parseLong((String) state.value(WorkflowControlConstant.USER_ID).orElse("0"));
            long appId =  Long.parseLong((String) state.value(WorkflowControlConstant.APP_ID).orElse("0"));

            // 生成可视化数据

            // 生成HTML展示页面

            // TODO  保存到  MinIO 文件系统并生成访问URL
            String visualUrl = saveAndGenerateUrl(aggregatedContent ,userInput, userId, appId);

            logger.info("可视化处理完成，生成访问URL: {}", visualUrl);
            node2Status.put(NODE_NAME, NodeStatus.COMPLETED);

            return Map.of(
                    WorkflowControlConstant.VISUAL_URL, visualUrl
//                    "visualization_data", visualizationData,
//                    "html_content", htmlContent
            );

        } catch (Exception e) {
            logger.error("可视化节点执行异常", e);
            node2Status.put(NODE_NAME, NodeStatus.FAILED);
            return Map.of(
                    WorkflowControlConstant.VISUAL_URL, "可视化处理失败：" + e.getMessage(),
                    "visualization_data", Map.of("error", e.getMessage())
            );
        } finally {
            logger.info("=== 可视化节点执行完成 ===");
        }
    }

    /**
     * 保存内容到MinIO并生成访问URL
     * 使用统一的数据存储服务处理书籍保存
     */
    protected String saveAndGenerateUrl(String content, String fileName, Long userId, Long appId) {
        try {
            // TODO 这里默认用一个存储桶
            String defaultBucket = minioUtils.getDefaultBucketName();
            String filePath = minioUtils.buildMinioObjectPath(FileDirBizEnums.BOOK, appId, userId, fileName + ".md", true);

            assert content != null;
            InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));

            // 使用MinioUtils上传文件
            minioUtils.uploadFile(defaultBucket, filePath, inputStream);

            // 使用统一的数据存储服务保存书籍信息
            Long bookId = workflowDataService.saveBook(appId, userId, fileName, filePath, "AI生成的智能内容");
            
            logger.info("书籍保存成功 - bookId: {}, filePath: {}", bookId, filePath);

            return filePath;
            
        } catch (Exception e) {
            logger.error("保存文件和书籍信息失败 - fileName: {}, userId: {}, appId: {}", fileName, userId, appId, e);
            throw new RuntimeException("保存失败: " + e.getMessage(), e);
        }
    }
}
